<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>🎵 小橘子音乐库</title>
<link rel="stylesheet" href="/static/style.css">
</head>
<body>

  <!-- 左侧主内容 -->
  <div class="main-content">
    <h2>🎶 小橘子音乐库</h2>

    {% if path %}
    <a href="/music/{{ parent }}" class="folder-link">⬅ 返回上一级</a>
    {% endif %}

    <h3>📁 文件夹</h3>
    <ul>
      {% for d in dirs %}
      <li><a href="/music/{{ path + '/' if path else '' }}{{ d }}" class="folder-link">{{ d }}</a></li>
      {% endfor %}
    </ul>

    <h3>🎵 歌曲列表</h3>
    <ul>
      {% for f in files %}
      <li>
        {{ f }}
        <button class="play-btn" data-path="{{ ((path ~ '/') if path else '') ~ f | urlencode }}">▶ 播放</button>
      </li>
      {% endfor %}
    </ul>

    <!-- 播放控制 -->
    <div class="player-controls">
      <label>播放模式：</label>
      <button onclick="setMode('normal')">🎧 普通</button>
      <button onclick="setMode('lossless')">💎 无损直通</button>
      <button onclick="setMode('decode')">🔬 高保真解码</button>
      <span id="currentMode">普通</span>
      <button id="decodePlayBtn" style="display:none;">▶ 播放/暂停</button>

      <label style="margin-left:20px;">音量：</label>
      <input type="range" id="volumeSlider" min="0" max="1" step="0.01" value="1">
    </div>

    <audio id="audioPlayer" controls></audio>
    <div id="progressContainer"><div id="progressBar"></div></div>
  </div>

  <!-- 右侧歌词 -->
  <div id="lyricsBox" class="lyrics-panel">
    <p>暂无歌词</p>
  </div>

<script>
// --- 状态变量 ---
let mode='normal';
let currentAlbumFiles=[];
let currentIndex=-1;
let currentPath="";
let lrcData=[];
let lrcTimer=null;

const audio=document.getElementById('audioPlayer');
const lyricsBox=document.getElementById('lyricsBox');
const progressContainer=document.getElementById('progressContainer');
const progressBar=document.getElementById('progressBar');
const decodePlayBtn=document.getElementById('decodePlayBtn');
const currentModeSpan=document.getElementById('currentMode');

const ctx=new (window.AudioContext||window.webkitAudioContext)();
let gainNode=ctx.createGain();
gainNode.connect(ctx.destination);
let decodeSource=null;
let decodeBuffer=null;
let decodeStartTime=0;
let decodePausedAt=0;
let isDecodePlaying=false;
let progressInterval=null;

// --- 播放模式切换 ---
function setMode(m){
    mode=m;
    stopDecode();
    isDecodePlaying=false;
    if(mode==='decode'){
        audio.style.display='none';
        progressContainer.style.display='block';
        decodePlayBtn.style.display='inline-block';
    } else {
        audio.style.display='block';
        progressContainer.style.display='block';
        decodePlayBtn.style.display='none';
        audio.pause();
    }
    currentModeSpan.textContent = mode==='normal'?'普通':mode==='lossless'?'无损直通':'高保真解码';
}

// --- 停止高保真播放 ---
function stopDecode(){
    if(decodeSource){ decodeSource.stop(); decodeSource.disconnect(); decodeSource=null; }
    decodePausedAt=0;
    clearInterval(progressInterval);
    progressBar.style.width='0%';
}

// --- 高保真播放 ---
function playDecode(buffer,start=0){
    decodeSource=ctx.createBufferSource();
    decodeSource.buffer=buffer;
    decodeSource.connect(gainNode);
    decodeSource.start(0,start);
    decodeStartTime=ctx.currentTime-start;
    decodeSource.onended=()=>{ clearInterval(progressInterval); decodeSource=null; isDecodePlaying=false; playNext(); };
    progressInterval=setInterval(()=>{
        const elapsed=ctx.currentTime-decodeStartTime;
        syncLyrics(elapsed);
        progressBar.style.width=Math.min(100,(elapsed/buffer.duration)*100)+'%';
    },200);
}

// --- 点击播放/暂停 ---
decodePlayBtn.addEventListener('click',()=>{
    if(!decodeBuffer) return;
    if(isDecodePlaying){
        stopDecode();
        decodePausedAt=ctx.currentTime-decodeStartTime;
        isDecodePlaying=false;
        decodePlayBtn.textContent='▶ 播放';
    } else {
        playDecode(decodeBuffer,decodePausedAt||0);
        isDecodePlaying=true;
        decodePlayBtn.textContent='⏸ 暂停';
    }
});

// --- 拖动进度条 ---
progressContainer.addEventListener('click',(e)=>{
    if(mode!=='decode'||!decodeBuffer) return;
    const rect=progressContainer.getBoundingClientRect();
    const percent=(e.clientX-rect.left)/rect.width;
    const newTime=decodeBuffer.duration*percent;
    stopDecode();
    playDecode(decodeBuffer,newTime);
    decodePausedAt=newTime;
    isDecodePlaying=true;
});

// --- 音量控制 ---
document.getElementById('volumeSlider').addEventListener('input',()=>{
    if(mode==='decode') gainNode.gain.value = document.getElementById('volumeSlider').value;
    else audio.volume = document.getElementById('volumeSlider').value;
});

// --- 歌词解析 ---
function parseLRC(raw){
    const lines = raw.split(/\r?\n/);
    const result = [];
    const timeReg = /\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/;
    for(const line of lines){
        const match = timeReg.exec(line);
        if(!match) continue;
        const min = parseInt(match[1]);
        const sec = parseInt(match[2]);
        const ms = match[3] ? parseInt(match[3].padEnd(3,'0')) : 0;
        const time = min*60 + sec + ms/1000;
        const text = line.replace(timeReg,'').trim();
        if(text) result.push({time,text});
    }
    return result.sort((a,b)=>a.time-b.time);
}

// --- 渲染歌词 ---
function showLyrics(lyrics){
    lyricsBox.innerHTML="";
    if(!lyrics||lyrics.length===0){ lyricsBox.innerHTML="<p>暂无歌词</p>"; return; }
    for(const l of lyrics){
        const p=document.createElement("p");
        p.textContent=l.text;
        lyricsBox.appendChild(p);
    }
}

// --- 同步歌词 ---
function syncLyrics(currentTime) {
  if (lrcData.length === 0) return;
  let idx = -1;
  for (let i = 0; i < lrcData.length; i++) {
    if (currentTime >= lrcData[i].time) idx = i;
  }
  const lines = lyricsBox.querySelectorAll("p");
  lines.forEach(l => l.classList.remove("active"));
  if (idx >= 0 && idx < lines.length) {
    lines[idx].classList.add("active");
    lyricsBox.scrollTo({top: lines[idx].offsetTop - lyricsBox.clientHeight / 2, behavior: "smooth"});
  }
}

// --- 加载歌词 ---
async function loadLyrics(path){
    const res=await fetch(`/lrc/${path}`);
    const data=await res.json();
    lrcData=parseLRC(data.lyrics||"");
    showLyrics(lrcData);
}

// --- 播放下一首 ---
function playNext(){
    if(currentAlbumFiles.length===0||currentIndex===-1) return;
    currentIndex++;
    if(currentIndex>=currentAlbumFiles.length){
        currentIndex=0;
    }
    const nextSong=currentAlbumFiles[currentIndex];
    const nextPath=(currentPath?currentPath+'/':'')+nextSong;
    play(nextPath);
}

// --- 播放 ---
async function play(path){
    await loadLyrics(path);

    // 停止 decode 播放
    stopDecode();

    audio.pause();
    audio.src = `/file/${path}`;

    // 显示进度条
    progressContainer.style.display = 'block';
    progressBar.style.width = '0%';

    if(mode==='decode'){
        const res=await fetch(`/file/${path}`);
        const buf=await res.arrayBuffer();
        decodeBuffer=await ctx.decodeAudioData(buf);
        playDecode(decodeBuffer);
        isDecodePlaying=true;
        decodePlayBtn.textContent='⏸ 暂停';
    } else {
        // 普通 / 无损模式，audio 播放
        audio.play();

        // 清除之前 interval
        clearInterval(progressInterval);
        progressInterval=setInterval(()=>{
            if(audio.duration){
                const percent = (audio.currentTime/audio.duration)*100;
                progressBar.style.width = percent + '%';
                syncLyrics(audio.currentTime);
            }
        },200);
    }
}

// --- 拖动进度条 ---
progressContainer.addEventListener('click',(e)=>{
    const rect=progressContainer.getBoundingClientRect();
    const percent=(e.clientX-rect.left)/rect.width;

    if(mode==='decode' && decodeBuffer){
        const newTime=decodeBuffer.duration*percent;
        stopDecode();
        playDecode(decodeBuffer,newTime);
        decodePausedAt=newTime;
        isDecodePlaying=true;
    } else {
        if(audio.duration){
            audio.currentTime = audio.duration * percent;
        }
    }
});

// --- 音频同步歌词 ---
audio.ontimeupdate=()=> syncLyrics(audio.currentTime);

// --- 播放按钮 ---
document.querySelectorAll('.play-btn').forEach((btn,index)=>{
    btn.addEventListener('click', async ()=>{
        const path=btn.getAttribute('data-path');
        currentIndex=index;
        currentPath="{{ path }}";
        const res=await fetch(`/api/music/${currentPath}`);
        const data=await res.json();
        currentAlbumFiles=data.files;
        play(path);
    });
});
</script>
</body>
</html>